package com.alex.springbootdemo.aop;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alex.springbootdemo.security.IgnoreUrlsConfig;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashMap;

@Aspect
@Component
@Slf4j
public class ValidateAspect {

    @Value("${api.validate}")
    private String validateUrl;

    @Autowired
    private IgnoreUrlsConfig ignoreUrlsConfig;

    @Pointcut("@annotation(org.springframework.web.bind.annotation.PostMapping)")
    public void controllerAspect() {
    }

    @Before("controllerAspect()")
    public void doBefore(JoinPoint joinPoint) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String requestURI = request.getRequestURI();
        String apiContextPath = request.getContextPath();
        String url = requestURI.substring(apiContextPath.length());
        //白名单请求直接放行
        PathMatcher pathMatcher = new AntPathMatcher();
        for (String path : ignoreUrlsConfig.getUrls()) {
            if (pathMatcher.match(path, request.getRequestURI())) {
                return;
            }
        }
        Object[] args = joinPoint.getArgs();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
        for (int i = 0; i < parameterAnnotations.length; i++) {
            for (Annotation annotation : parameterAnnotations[i]) {
                if (annotation instanceof RequestBody) {
                    Object arg = args[i];
                    String jsonString = JSONObject.toJSONString(arg);
                    HashMap<String, Object> map = JSONObject.parseObject(jsonString, HashMap.class);
                    HashMap<String, Object> paramMap = new HashMap<>();
                    paramMap.put("url", url);
                    paramMap.put("argsMap", map);
                    HttpRequest httpRequest = HttpUtil.createPost(validateUrl);
                    httpRequest.header("Content-Type", "application/json");
                    httpRequest.body(JSONObject.toJSONString(paramMap));
                    HttpResponse response = httpRequest.execute();
                    int status = response.getStatus();
                    if (status == 200) {
                        String result = response.body();
                        HashMap resultMap = JSONObject.parseObject(result, HashMap.class);
                        HashMap dataMap = JSONObject.parseObject(resultMap.get("data").toString(), HashMap.class);
                        boolean flag = (boolean) dataMap.get("result");
                        if (!flag) {
                            throw new RuntimeException((String) dataMap.get("errMsg"));
                        }
                    }
                }
            }
        }
    }
}
